﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Windows.Forms;
using System.Reflection;
//MicroDesigner
using Jc.MicroDesigner.Drawings;
using Jc.MicroDesigner.Management;
using Jc.MicroDesigner.Drawings.Tools;
using Jc.MicroDesigner.Objects;

namespace Jc.MicroDesigner.ToolWindows
{
    /// <summary>
    /// Класс для управления инструментами рисования
    /// </summary>
    public class ToolBoxObject : IToolBox
    {
        private ObjectManager _Manager = null;
        private List<DrawingTool> _Tools = new List<DrawingTool>();
        private DrawingTool _ActiveTool = null;
        private DrawPanel _Canvas = null;
        private string _Config = "";

        private ListView _View = null;
        private ToolStrip _ToolBar = null;

        #region IToolBox Members

        public DrawingTool ActiveTool
        {
            get { return _ActiveTool; }
        }

        public List<DrawingTool> Tools
        {
            get { return _Tools; }
        }

        public ObjectManager ObjManager
        {
            get { return _Manager; }
        }

        #endregion

        /// <summary>
        /// Загрузить инструменты
        /// </summary>
        public void LoadTools()
        {
            try
            {
                if (File.Exists(_Config))
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(_Config);
                    XmlNode root = null;
                    int i = 0;
                    while ((i < doc.ChildNodes.Count) && (doc.ChildNodes[i].Name != "root"))
                        i++;
                    if (i < doc.ChildNodes.Count)
                    {
                        root = doc.ChildNodes[i];
                        XmlNode tools = root.FirstChild;
                        foreach (XmlNode node in tools.ChildNodes)
                        {
                            string type = node.Attributes["type"].Value;
                            string title = node.Attributes["title"].Value;
                            string assm = node.Attributes["assembly"].Value.Replace(":", _Manager.AppPath);
                            Assembly asm = Assembly.LoadFile(assm);
                            Type t = asm.GetType(type);
                            CircuitElementTool tool = new CircuitElementTool(t, title);
                            _Tools.Add(tool);
                        }
                    }
                }
                // загружать все элементы из ObjectsLib автоматом
                AssemblyClassAnalyser analyzer = new AssemblyClassAnalyser(Path.Combine(_Manager.AppPath,"ObjectsLib.dll"));
                List<Type> types = analyzer.GetListOfPublicClass(typeof(CircuitElement));
                foreach (Type t in types)
                {
                    string name = t.Name;
                    string category = "Общие";
                    object[] fields = t.GetCustomAttributes(typeof(DrawingToolItemAttribute), true);
                    if (fields.Length > 0)
                    {
                        DrawingToolItemAttribute attr = (DrawingToolItemAttribute)fields[0];
                        name = attr.ToolName;
                        category = attr.Category;
                    }
                    CircuitElementTool tool = new CircuitElementTool(t, name, category);
                    _Tools.Add(tool);
                }
                //Все файлы конфигурации типа CompositeElement располагаются в ./Config/Schemes/ и ./Config/User

                //Schemes
                string schemes_dir = _Manager.AppPath + Path.DirectorySeparatorChar + "Config" + Path.DirectorySeparatorChar + "Schemes";
                if (Directory.Exists(schemes_dir))
                {
                    DirectoryInfo schemes = new DirectoryInfo(schemes_dir);
                    FileInfo[] filelist = schemes.GetFiles("*.xml");
                    for (int i = 0; i < filelist.Length; i++)
                        _Tools.Add(new CompositeTool(_Manager,filelist[i].Name));
                }

                //User
                string user_dir = _Manager.AppPath + Path.DirectorySeparatorChar + "Config" + Path.DirectorySeparatorChar + "User";
                if (Directory.Exists(user_dir))
                {
                    DirectoryInfo users = new DirectoryInfo(user_dir);
                    FileInfo[] filelist = users.GetFiles("*.xml");
                    for (int i = 0; i < filelist.Length; i++)
                        _Tools.Add(new CompositeTool(_Manager,filelist[i].Name));
                }
            }
            catch (Exception ex)
            {
                Exceptions.ExceptionDialog.ShowException(ex, "Ошибка", "Ошибка при загрузке панели инструментов");
            }
        }

        /// <summary>
        /// Сохранить
        /// </summary>
        public void SaveTools()
        {
           //TODO: В дальнейшем панель инструментов будет настраиваться и сохранять инструменты в конфиг
        }

        /// <summary>
        /// Создать объект управления инструментами
        /// </summary>
        /// <param name="manager"></param>
        /// <param name="config"></param>
        public ToolBoxObject(ObjectManager manager, string config)
        {
            _Manager = manager;
            _Tools.AddRange(new DrawingTool[]{
                                    new MoveTool(),
                                    new WireTool(),
                                    new TextTool(),
                                    new RegionTool()}
                                    );
            _ActiveTool = _Tools[0];
            _Config = config;
            LoadTools();
        }

        /// <summary>
        /// Заполнить список элементами
        /// </summary>
        /// <param name="view"></param>
        public void PopulateListView(ListView view)
        {
            _View = view;

            view.TabStop = false;
            view.MultiSelect = false;
            view.Items.Clear();
            view.View = View.Details;

            ListViewGroup tools = new ListViewGroup("Инструменты");

            Dictionary<string, ListViewGroup> groups = new Dictionary<string, ListViewGroup>();
            groups.Add("Инструменты", tools);
            view.Groups.Add(tools);

            foreach (DrawingTool tool in _Tools)
            {
                ListViewItem item = new ListViewItem(tool.Name);
                if (String.IsNullOrEmpty(tool.Category))
                    item.Group = tools;
                else
                {
                    if (groups.ContainsKey(tool.Category))
                        item.Group = groups[tool.Category];
                    else
                    {
                        ListViewGroup group = new ListViewGroup(tool.Category);
                        groups.Add(tool.Category,group);
                        view.Groups.Add(group);
                        item.Group = group;
                    }
                }

                view.Items.Add(item);
            }
            view.MouseClick += new MouseEventHandler(view_MouseClick);
            view.SelectedIndexChanged += new EventHandler(view_SelectedIndexChanged);
        }

        /// <summary>
        /// Заполнить панель
        /// </summary>
        /// <param name="toolstrip"></param>
        public void PopulateToolStrip(MenuStrip toolstrip)
        {
            _ToolBar = toolstrip;

            toolstrip.Items.Clear();
            ToolStripItem mouse = new ToolStripButton(Properties.Resources.Mouse);
            mouse.Text = "Мышь";
            mouse.Click += new EventHandler(mouse_Click);
            toolstrip.Items.Add(mouse);

            ToolStripItem wire = new ToolStripButton(Properties.Resources.Wire);
            wire.Text = "Провод";
            wire.Click += new EventHandler(wire_Click);
            toolstrip.Items.Add(wire);

            ToolStripItem text = new ToolStripButton(Properties.Resources.Label);
            text.Text = "Текст";
            text.Click += new EventHandler(text_Click);
            toolstrip.Items.Add(text);

            ToolStripItem region = new ToolStripButton(Properties.Resources.RegionTool);
            region.Text = "Выделение";
            region.Click += new EventHandler(region_Click);
            toolstrip.Items.Add(region);

            for (int i = 0; i < toolstrip.Items.Count; i++)
                toolstrip.Items[i].ToolTipText = "";
        }

        /// <summary>
        /// Холст схемы
        /// </summary>
        public DrawPanel Canvas
        {
            get
            {
                return _Canvas;
            }
            set
            {
                _Canvas = value;
            }
        }

        #region Events

        void SelectItem(DrawingTool tool)
        {
            if (_ActiveTool != null)
                _ActiveTool.OnDeactivate();
            _ActiveTool = tool;
            _ActiveTool.OnActivate(this);
            if (_Canvas != null)
                _Canvas.Cursor = _ActiveTool.ToolCursor;
            int index = _Tools.IndexOf(tool);
            if ((_View != null))
            {
                if (!_View.SelectedIndices.Contains(index))
                {
                    _View.SelectedItems.Clear();
                    _View.SelectedIndices.Add(index);
                }
            }
        }

        void wire_Click(object sender, EventArgs e)
        {
            SelectItem(_Tools[1]);
        }

        void mouse_Click(object sender, EventArgs e)
        {
            SelectItem(_Tools[0]);
        }

        void text_Click(object sender, EventArgs e)
        {
            SelectItem(_Tools[2]);
        }

        void region_Click(object sender, EventArgs e)
        {
            SelectItem(_Tools[3]);
        }

        void view_MouseClick(object sender, MouseEventArgs e)
        {
            ListView view = sender as ListView;
            if (view.SelectedIndices.Count > 0)
            {
                SelectItem(_Tools[view.SelectedIndices[0]]);
            }
        }

        void view_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListView view = sender as ListView;
            if (view.SelectedIndices.Count > 0)
            {
                SelectItem(_Tools[view.SelectedIndices[0]]);
            }
        }

        #endregion
    }
}